#ifndef _QUADRUPLE_H_
#define _QUADRUPLE_H_

////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////////////////////

namespace Types {

////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////

/**
 *  Generic quadruple class.
 *	This class creates a generic quadruple.
 */
template <typename T1, typename T2, typename T3, typename T4>
class Quadruple {

	public:

		/// Quadruple creation with default values
		Quadruple() {}

		/// Quadruple creation with initialisation values
		Quadruple(
			const T1 & first,
			const T2 & second,
			const T3 & third,
			const T4 & fourth
		) : first(first), second(second), third(third), fourth(fourth) {}

		/// Create a copy of the given instance
		template <typename OT1, typename OT2, typename OT3, typename OT4>
		Quadruple(const Quadruple<OT1,OT2,OT3,OT4> & inst)
		:	first(static_cast<T1>(inst.GetFirst())),
			second(static_cast<T2>(inst.GetSecond())),
			third(static_cast<T3>(inst.GetThird())),
			fourth(static_cast<T4>(inst.GetFourth()))
		{}
		
		/// Affectation operator
		template <typename OT1, typename OT2, typename OT3, typename OT4>
		Quadruple<T1,T2,T3,T4> & operator = (const Quadruple<OT1,OT2,OT3,OT4> & inst) {
			if (this != &inst) {
				this->first		= static_cast<T1>(inst.GetFirst());
				this->second	= static_cast<T2>(inst.GetSecond());
				this->third		= static_cast<T3>(inst.GetThird());
				this->fourth	= static_cast<T4>(inst.GetFourth());
			}
			return *this;
		}
		
		/// Returns the first value
		inline T1 & First() { return this->first; }
		inline const T1 & GetFirst() const { return this->first; }
		
		/// Returns the second value
		inline T2 & Second() { return this->second; }
		inline const T2 & GetSecond() const { return this->second; }
		
		/// Returns the third value
		inline T3 & Third() { return this->third; }
		inline const T3 & GetThird() const { return this->third; }
		
		/// Returns the fourth value
		inline T4 & Fourth() { return this->fourth; }
		inline const T4 & GetFourth() const { return this->fourth; }
		
	protected:
		
		/// First value
		T1 first;
		
		/// Second value
		T2 second;
		
		/// Third value
		T3 third;
		
		/// Fourth value
		T4 fourth;

};

////////////////////////////////////////////////////////////////////////////////
// Closing Namespaces
////////////////////////////////////////////////////////////////////////////////

}

////////////////////////////////////////////////////////////////////////////////

#endif
